home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
001
/
pibt40s2.arc
/
PIB4010A.MOD
< prev
next >
Wrap
Text File
|
1987-05-25
|
51KB
|
866 lines
PROCEDURE Emulate_TEK4010;
(*----------------------------------------------------------------------*)
(* Emulate_TEK4010 --- Emulate TekTronix 4010 terminal *)
(*----------------------------------------------------------------------*)
(* *)
(* Author: Philip R. Burns *)
(* Date: April, 1986 (Version 1.0) *)
(* November, 1986 (Version 2.0 -- EGA support) *)
(* February, 1987 (Version 2.1 -- fix minor bugs *)
(* March, 1987 (Version 2.2 -- speed up display *)
(* *)
(* Systems: For MS-DOS on IBM PCs and close compatibles only. *)
(* *)
(* History: Original with me. *)
(* *)
(* This emulator uses the high-resolution graphics mode *)
(* (640x200) of the standard IBM color graphics adapter. *)
(* Only graphics output is emulated, not graphics input. *)
(* The display consists of 33 rather than 35 lines of text, *)
(* because of the limited display resolution available on the *)
(* PC. *)
(* *)
(* Suggestions for improvements or corrections are welcome. *)
(* Please leave messages on Gene Plantz's BBS (312) 882 4145 *)
(* or Ron Fox's BBS (312) 940 6496. *)
(* *)
(* IF you use this code in your own programs, please be nice *)
(* and give proper credit. *)
(* *)
(*----------------------------------------------------------------------*)
TYPE
Graphics_State = ( Text_Plot, Vector_Plot_Start, Vector_Plot,
Point_Plot_Start, Point_Plot, Graphics_Input );
VAR
Done : BOOLEAN (* TRUE to exit terminal emulation mode *);
Ch : CHAR (* Character read/written *);
B : BOOLEAN (* Boolean flag *);
Regs : RegPack (* For MS DOS interfacing *);
FlagG : Graphics_State (* Current graphics state *);
CursorX : INTEGER (* X position of cursor *);
CursorY : INTEGER (* Y position of cursor *);
Reset_T : BOOLEAN (* Dummy for reset of terminal *);
EGA_On : BOOLEAN (* TRUE if EGA installed *);
XFactor : REAL (* Horizontal scaling factor *);
YFactor : REAL (* Vertical scaling factor *);
YMax : INTEGER (* Maximum Y value ==> 199, 349 *);
YMaxM1 : INTEGER (* Maximum Y value - 1 ==> 198, 348 *);
YInc : INTEGER (* Increment in Y for characters *);
GMode : INTEGER (* Graphics mode type *);
ClrScr_Req : BOOLEAN (* TRUE if clear screen request typed *);
Save_SUpper: BOOLEAN (* Save send_upper_case_only flag *);
CONST
Prev_Ch : CHAR = ^@;
Hx : INTEGER = 0;
Hy : INTEGER = 0;
Lx : INTEGER = 0;
Ly : INTEGER = 0;
Old : INTEGER = 0;
LeftH : BOOLEAN = TRUE;
LastX : INTEGER = 0;
LastY : INTEGER = 0;
CONST
Ch_FF = #12 (* Form Feed *);
Ch_CR = #13 (* Carriage Return *);
Ch_SO = #14 (* Start grahics *);
Ch_SI = #15 (* End graphics *);
Ch_SUB = #26 (* EOF Character *);
Ch_ESC = #27 (* Escape *);
Ch_FS = #28 (* Graphics start *);
Ch_GS = #29 (* Graphics start *);
Ch_RS = #30 (* Inc. plot start *);
Ch_US = #31 (* Graphics end *);
(* STRUCTURED *) CONST (* Starting bytes for each CGA scan line *)
Scan_Line_Table : ARRAY[0..199] OF INTEGER =
( 0, 8192, 80, 8272, 160, 8352, 240, 8432,
320, 8512, 400, 8592, 480, 8672, 560, 8752,
640, 8832, 720, 8912, 800, 8992, 880, 9072,
960, 9152, 1040, 9232, 1120, 9312, 1200, 9392,
1280, 9472, 1360, 9552, 1440, 9632, 1520, 9712,
1600, 9792, 1680, 9872, 1760, 9952, 1840, 10032,
1920, 10112, 2000, 10192, 2080, 10272, 2160, 10352,
2240, 10432, 2320, 10512, 2400, 10592, 2480, 10672,
2560, 10752, 2640, 10832, 2720, 10912, 2800, 10992,
2880, 11072, 2960, 11152, 3040, 11232, 3120, 11312,
3200, 11392, 3280, 11472, 3360, 11552, 3440, 11632,
3520, 11712, 3600, 11792, 3680, 11872, 3760, 11952,
3840, 12032, 3920, 12112, 4000, 12192, 4080, 12272,
4160, 12352, 4240, 12432, 4320, 12512, 4400, 12592,
4480, 12672, 4560, 12752, 4640, 12832, 4720, 12912,
4800, 12992, 4880, 13072, 4960, 13152, 5040, 13232,
5120, 13312, 5200, 13392, 5280, 13472, 5360, 13552,
5440, 13632, 5520, 13712, 5600, 13792, 5680, 13872,
5760, 13952, 5840, 14032, 5920, 14112, 6000, 14192,
6080, 14272, 6160, 14352, 6240, 14432, 6320, 14512,
6400, 14592, 6480, 14672, 6560, 14752, 6640, 14832,
6720, 14912, 6800, 14992, 6880, 15072, 6960, 15152,
7040, 15232, 7120, 15312, 7200, 15392, 7280, 15472,
7360, 15552, 7440, 15632, 7520, 15712, 7600, 15792,
7680, 15872, 7760, 15952, 7840, 16032, 7920, 16112 );
(*----------------------------------------------------------------------*)
(* Plot_Point --- Plot one point in graphics display *)
(*----------------------------------------------------------------------*)
PROCEDURE Plot_Point( X , Y: INTEGER );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Plot_Point *)
(* *)
(* Purpose: Plots one pixel in high-resolution graphics screen. *)
(* *)
(* Calling Sequence: *)
(* *)
(* Plot_Point( X , Y : INTEGER ); *)
(* *)
(* X --- Horizontal coordinate (0--639) *)
(* Y --- Vertical coordinate (0--199) *)
(* *)
(*----------------------------------------------------------------------*)
BEGIN (* Plot_Point *)
INLINE(
{;}
{; Check if we are to use BIOS to plot pixel}
{;}
$F6/$06/>WRITE_SCREEN_MEMORY/$01{ TEST Byte [>Write_Screen_Memory],1 ;Check if direct scren writes}
/$74/$31 { JZ Bios ;No -- use BIOS}
{;}
{; Write pixel directly to screen memory}
{;}
/$8B/$96/>Y { MOV DX,[BP+>Y] ; Get Y}
/$8D/$1E/>SCAN_LINE_TABLE { LEA BX,[>Scan_Line_Table] ; Get scan line table address}
/$D1/$E2 { SHL DX,1 ; Y * 2 for integer offset}
/$01/$D3 { ADD BX,DX ; Get offset of entry for Y}
/$2E/$8B/$1F { CS: MOV BX,[BX] ; Get offset for Y}
{;}
/$8B/$96/>X { MOV DX,[BP+>X] ; Get X}
/$89/$D0 { MOV AX,DX}
/$B1/$03 { MOV CL,3 ;}
/$D3/$EA { SHR DX,CL ; X DIV 8 = Byte offset within row}
/$01/$D3 { ADD BX,DX ; Byte location in screen memory}
/$25/$07/$00 { AND AX,7 ; X MOD 8}
/$BA/$80/$00 { MOV DX,$80 ; 1 bit in leftmost position}
/$89/$C1 { MOV CX,AX ; shift count}
/$D3/$EA { SHR DX,CL ; 1 bit in proper position}
/$C4/$3E/>GRAPHICS_SCREEN { LES DI,[>Graphics_Screen] ; Get screen address}
/$01/$DF { ADD DI,BX ; Get byte address}
/$26/$08/$15 { ES: OR BYTE PTR [DI],DL ; Get byte to alter}
/$E9/$0F/$00 { JMP Exit ; Return to caller}
{;}
{; Plot pixel using BIOS}
{;}
/$55 {Bios: PUSH BP ; Save BP in case BIOS zaps it}
/$B8/$01/$0C { MOV AX,$0C01 ; Plot pixel function}
/$8B/$8E/>X { MOV CX,[BP+>X] ; Get horizontal position}
/$8B/$96/>Y { MOV DX,[BP+>Y] ; Get vertical position}
/$CD/$10 { INT $10 ; Plot the pixel via BIOS}
/$5D { POP BP ; Restore BP}
{;}
{Exit:}
);
END (* Plot_Point *);
(*----------------------------------------------------------------------*)
(* XOR_Plot_Point --- Plot one point in graphics display using XOR *)
(*----------------------------------------------------------------------*)
PROCEDURE XOR_Plot_Point( X , Y: INTEGER );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: XOR_Plot_Point *)
(* *)
(* Purpose: Plots one pixel in high-res graphics using XOR. *)
(* *)
(* Calling Sequence: *)
(* *)
(* XOR_Plot_Point( X , Y : INTEGER ); *)
(* *)
(* X --- Horizontal coordinate (0--639) *)
(* Y --- Vertical coordinate (0--199) *)
(* *)
(*----------------------------------------------------------------------*)
BEGIN (* XOR_Plot_Point *)
INLINE(
{;}
{; Check if we are to use BIOS to plot pixel}
{;}
$F6/$06/>WRITE_SCREEN_MEMORY/$01{ TEST Byte [>Write_Screen_Memory],1 ;Check if direct scren writes}
/$74/$31 { JZ Bios ;No -- use BIOS}
{;}
{; XOR pixel directly to screen memory}
{;}
/$8B/$96/>Y { MOV DX,[BP+>Y] ; Get Y}
/$8D/$1E/>SCAN_LINE_TABLE { LEA BX,[>Scan_Line_Table] ; Get scan line table address}
/$D1/$E2 { SHL DX,1 ; Y * 2 for integer offset}
/$01/$D3 { ADD BX,DX ; Get offset of entry for Y}
/$2E/$8B/$1F { CS: MOV BX,[BX] ; Get offset for Y}
{;}
/$8B/$96/>X { MOV DX,[BP+>X] ; Get X}
/$89/$D0 { MOV AX,DX}
/$B1/$03 { MOV CL,3 ;}
/$D3/$EA { SHR DX,CL ; X DIV 8 = Byte offset within row}
/$01/$D3 { ADD BX,DX ; Byte location in screen memory}
/$25/$07/$00 { AND AX,7 ; X MOD 8}
/$BA/$80/$00 { MOV DX,$80 ; 1 bit in leftmost position}
/$89/$C1 { MOV CX,AX ; shift count}
/$D3/$EA { SHR DX,CL ; 1 bit in proper position}
/$C4/$3E/>GRAPHICS_SCREEN { LES DI,[>Graphics_Screen] ; Get screen address}
/$01/$DF { ADD DI,BX ; Get byte address}
/$26/$30/$15 { ES: XOR BYTE PTR [DI],DL ; Get byte to alter}
/$E9/$0F/$00 { JMP Exit ; Return to caller}
{;}
{; Plot pixel using BIOS}
{;}
/$55 {Bios: PUSH BP ; Save BP in case BIOS zaps it}
/$B8/$81/$0C { MOV AX,$0C81 ; Plot pixel function using XOR}
/$8B/$8E/>X { MOV CX,[BP+>X] ; Get horizontal position}
/$8B/$96/>Y { MOV DX,[BP+>Y] ; Get vertical position}
/$CD/$10 { INT $10 ; Plot the pixel via BIOS}
/$5D { POP BP ; Restore BP}
{;}
{Exit:}
);
END (* XOR_Plot_Point *);
(*----------------------------------------------------------------------*)
(* Clear_Graphics_Screen --- Clear screen and home cursor *)
(*----------------------------------------------------------------------*)
PROCEDURE Clear_Graphics_Screen;
VAR
Regs : RegPack (* For MS DOS interfacing *);
BEGIN (* Clear_Graphics_Screen *)
Set_Graphics_Colors( EGA_On, GMode,
Graphics_Foreground_Color, Graphics_BackGround_Color );
(* Move cursor to upper left-hand *)
(* cursor. *)
Graphics_XPos := 0;
Graphics_YPos := 5;
CursorX := 0;
CursorY := 5;
LeftH := TRUE;
Prev_Ch := CHR( 0 );
END (* Clear_Graphics_Screen *);
(*--------------------------------------------------------------------------*)
(* Draw_Line -- Draw line between two points, low res. mode *)
(*--------------------------------------------------------------------------*)
PROCEDURE Draw_Line( X1, Y1, X2, Y2: INTEGER );
(*--------------------------------------------------------------------------*)
(* *)
(* Procedure: Draw_Line *)
(* *)
(* Purpose: Draws line between two points in hi-res. graphics mode *)
(* *)
(* Calling Sequence: *)
(* *)
(* Draw_Line( X1 , Y1 , X2, Y2, LineCol : INTEGER ); *)
(* *)
(* X1 -- Horizontal postion (0 through 639), 1st point *)
(* Y1 -- Vertical position (0 through 119), 1st point *)
(* X2 -- Horizontal postion (0 through 639), 2nd point *)
(* Y2 -- Vertical position (0 through 119), 2nd point *)
(* *)
(* Calls: TurnOnTimeSharing *)
(* TurnOffTimeSharing *)
(* Get_Screen_Address *)
(* *)
(* Remarks: An incremental plotter algorithm is used. *)
(* *)
(*--------------------------------------------------------------------------*)
VAR
LongDelta : INTEGER;
LongStep : INTEGER;
ShortStep : INTEGER;
LineStart : INTEGER;
LineStop : INTEGER;
BEGIN (* Draw_Line *)
(* Turn off timesharing while drawing *)
IF ( MultiTasker = DoubleDos ) THEN
BEGIN
TurnOffTimeSharing;
Get_Screen_Address( Graphics_Screen );
END;
INLINE(
$C7/$86/>LONGSTEP/$01/$00 { MOV WORD PTR >LongStep[BP],1 ; assume motion down or right}
/$8B/$B6/>X2 { MOV SI,>X2[BP]}
/$2B/$B6/>X1 { SUB SI,>X1[BP] ; get BP := LongDelta}
/$7D/$06 { JGE PL1 ; if X1 <= X2 then no change}
/$F7/$9E/>LONGSTEP { NEG WORD PTR >LongStep[BP] ; ELSE LongStep := -1 (motion up or left)}
/$F7/$DE { NEG SI ; LongDelta = abs(LongDelta)}
{PL1:}
/$C7/$86/>SHORTSTEP/$01/$00 { MOV WORD PTR >ShortStep[BP],1 ; assume motion down or right}
/$8B/$86/>Y2 { MOV AX,>Y2[BP]}
/$2B/$86/>Y1 { SUB AX,>Y1[BP] ; get AX := shortdelta}
/$7D/$06 { JGE PL2 ; if y1 <= y2 then no change}
/$F7/$9E/>SHORTSTEP { NEG WORD PTR >ShortStep[BP] ; else, ShortStep = -1 (motion up or left)}
/$F7/$D8 { NEG AX ; shortdelta = abs(shortdelta)}
{PL2:}
/$C7/$86/>LINESTART/$00/$00 { MOV WORD PTR >LineStart[BP],0 ; assume no skip length}
/$8B/$8E/>X1 { MOV CX,>X1[BP] ; x coordinate in CX}
/$8B/$96/>Y1 { MOV DX,>Y1[BP] ; y coordinate in DX}
/$39/$F0 { CMP AX,SI ; is shortdelta longer than LongDelta?}
/$77/$40 { JA AltCode ; yes, use alternate drawing code}
{;}
{; Do following when line has slope between 0 and 1}
{;}
/$89/$B6/>LINESTOP { MOV >LineStop[BP],SI ; assume length = LongDelta}
/$89/$F7 { MOV DI,SI ; set up the cycle pointer}
/$D1/$EF { SHR DI,1 ; cycle := LongDelta/2}
/$89/$B6/>LONGDELTA { MOV >LongDelta[BP],SI}
/$BE/$00/$00 { MOV SI,0 ; initialize loop counter}
{NormLoop:}
/$3B/$B6/>LINESTART { CMP SI,>LineStart[BP] ; start to plot yet???}
/$7C/$0D { JL PL5 ; no, skip}
{;}
/$50 { PUSH AX ;Save registers}
/$53 { PUSH BX}
/$51 { PUSH CX}
/$52 { PUSH DX}
/$57 { PUSH DI}
{;}
/$E8/$6E/$00 { CALL PlotDot ;Plot pixel}
{;}
/$5F { POP DI ;Restore registers}
/$5A { POP DX}
/$59 { POP CX}
/$5B { POP BX}
/$58 { POP AX}
{;}
{PL5:}
/$03/$8E/>LONGSTEP { ADD CX,>LongStep[BP] ; always move along the X AXis}
/$01/$C7 { ADD DI,AX ; cycle = cycle + shortdelta}
/$3B/$BE/>LONGDELTA { CMP DI,>LongDelta[BP] ; is cycle >= LongDelta?}
/$7C/$08 { JL PL6 ; no skip (don't move along y AXis yet}
/$2B/$BE/>LONGDELTA { SUB DI,>LongDelta[BP] ; yes, reset cycle pointer}
/$03/$96/>SHORTSTEP { ADD DX,>ShortStep[BP] ; and bump the y coordinate}
{PL6:}
/$46 { INC SI ; bump dot counter}
/$3B/$B6/>LINESTOP { CMP SI,>LineStop[BP] ; done??}
/$76/$D2 { JBE NormLoop ; no, plot next dot}
/$E9/$85/$00 { JMP PLExit ; yes, go to commom exit code}
{;}
{; Do following when slope has absolute value > 1}
{;}
{AltCode:}
/$96 { XCHG AX,SI ; swap LongDelta, shortdelta}
/$8B/$BE/>LONGSTEP { MOV DI,>LongStep[BP] ;}
/$87/$BE/>SHORTSTEP { XCHG >ShortStep[BP],DI}
/$89/$BE/>LONGSTEP { MOV >LongStep[BP],DI ; swap LongStep, ShortStep}
/$89/$B6/>LINESTOP { MOV >LineStop[BP],SI ; assume length = LongDelta}
/$89/$F7 { MOV DI,SI ; set up cycle pointer}
/$D1/$EF { SHR DI,1 ; cycle := LongDelta/2}
/$89/$B6/>LONGDELTA { MOV >LongDelta[BP],SI}
/$BE/$00/$00 { MOV SI,0 ; initialize loop counter}
{AltLoop:}
/$3B/$B6/>LINESTART { CMP SI,>LineStart[BP] ; start to plot yet?}
/$7C/$0B { JL PL8 ; no, skip}
{;}
/$50 { PUSH AX ;Save registers}
/$51 { PUSH CX}
/$52 { PUSH DX}
/$57 { PUSH DI}
{;}
/$E8/$22/$00 { CALL PlotDot ;Plot pixel}
{;}
/$5F { POP DI ;Restore registers}
/$5A { POP DX}
/$59 { POP CX}
/$58 { POP AX}
{;}
{PL8:}
/$03/$96/>LONGSTEP { ADD DX,>LongStep[BP] ; always move along Y AXis}
/$01/$C7 { ADD DI,AX ; cycle := cycle + shortdelta}
/$3B/$BE/>LONGDELTA { CMP DI,>LongDelta[BP] ; is cycle >= long delta???}
/$7C/$08 { JL PL9 ; no, skip (don't move along x AXis yet)}
/$2B/$BE/>LONGDELTA { SUB DI,>LongDelta[BP] ; yes, reset cycle pointer}
/$03/$8E/>SHORTSTEP { ADD CX,>ShortStep[BP] ; and bump x coordinate}
{PL9:}
/$46 { INC SI ; bump dot counter}
/$3B/$B6/>LINESTOP { CMP SI,>LineStop[BP] ; done???}
/$76/$D4 { JBE AltLoop ; no, plot next dot}
/$E9/$3A/$00 { JMP PLExit ; yes, go to common exit}
{;}
{PlotDot: ;PROC Near}
{;}
{; Check if we are to use BIOS to plot pixel}
{;}
/$F6/$06/>WRITE_SCREEN_MEMORY/$01{ TEST Byte [>Write_Screen_Memory],1 ;Check if direct scren writes}
/$74/$2B { JZ Bios ;No -- use BIOS}
{;}
{; Write pixel directly to screen memory}
{;}
/$8D/$1E/>SCAN_LINE_TABLE { LEA BX,[>Scan_Line_Table] ; Get scan line table address}
/$D1/$E2 { SHL DX,1 ; Y * 2 for integer offset}
/$01/$D3 { ADD BX,DX ; Get offset of entry for Y}
/$2E/$8B/$1F { CS: MOV BX,[BX] ; Get offset for Y}
{;}
/$89/$CA { MOV DX,CX ; Get X}
/$89/$C8 { MOV AX,CX}
/$B1/$03 { MOV CL,3 ;}
/$D3/$EA { SHR DX,CL ; X DIV 8 = Byte offset within row}
/$01/$D3 { ADD BX,DX ; Byte location in screen memory}
/$25/$07/$00 { AND AX,7 ; X MOD 8}
/$BA/$80/$00 { MOV DX,$80 ; 1 bit in leftmost position}
/$89/$C1 { MOV CX,AX ; shift count}
/$D3/$EA { SHR DX,CL ; 1 bit in proper position}
/$C4/$3E/>GRAPHICS_SCREEN { LES DI,[>Graphics_Screen] ; Get screen address}
/$01/$DF { ADD DI,BX ; Get byte address}
/$26/$08/$15 { ES: OR BYTE PTR [DI],DL ; Get byte to alter}
/$E9/$07/$00 { JMP Exit ; Return to caller}
{;}
{; Plot pixel using BIOS}
{;}
/$55 {Bios: PUSH BP ; Save BP in case BIOS zaps it}
/$B8/$01/$0C { MOV AX,$0C01 ; Plot pixel function}
/$CD/$10 { INT $10 ; Plot the pixel via BIOS}
/$5D { POP BP ; Restore BP}
{;}
{Exit:}
/$C3 { RET}
{;}
{PLExit:}
);
(* Restore timesharing mode *)
IF ( MultiTasker = DoubleDos ) THEN
TurnOnTimeSharing;
END (* Draw_Line *);
(*----------------------------------------------------------------------*)
(* Plot_Char --- Interpret current char as text to display *)
(*----------------------------------------------------------------------*)
PROCEDURE Plot_Char( Ch: CHAR; X: INTEGER; Y: INTEGER );
VAR
I : INTEGER;
K1 : INTEGER;
K2 : INTEGER;
XB : INTEGER;
XO : INTEGER;
XO1 : INTEGER;
XS : INTEGER;
XSL : INTEGER;
Do_XOR : BOOLEAN;
(* Holds point plot routine offset *)
(* STRUCTURED *) CONST
Point_Plot_Addr : INTEGER = 0;
(* Shape table for characters *)
(* STRUCTURED *) CONST
Char_Bits_Table: ARRAY[0..581] OF BYTE =
( 0, 0, 0, 0, 0, 0,
0, 96, 0, 96, 96, 96,
0, 0, 0, 0, 216, 216,
0, 80, 248, 80, 248, 80,
0, 240, 40, 112, 160, 120,
0, 152, 88, 32, 208, 200,
0, 16, 120, 144, 144, 112,
0, 0, 0, 32, 48, 48,
0, 32, 64, 64, 64, 32,
0, 64, 32, 32, 32, 64,
0, 136, 80, 248, 80, 136,
0, 32, 32, 248, 32, 32,
0, 64, 96, 0, 0, 0,
0, 0, 0, 240, 0, 0,
0, 24, 24, 0, 0, 0,
0, 128, 64, 32, 16, 8,
0, 112, 136, 168, 136, 112,
0, 112, 32, 32, 96, 32,
0, 248, 96, 16, 136, 112,
0, 112, 136, 48, 136, 112,
0, 16, 248, 144, 80, 32,
0, 240, 8, 240, 128, 248,
0, 112, 136, 240, 128, 112,
0, 64, 32, 16, 8, 120,
0, 112, 136, 112, 136, 112,
0, 112, 8, 120, 136, 112,
0, 96, 96, 0, 96, 96,
0, 64, 96, 0, 96, 96,
0, 16, 32, 64, 32, 16,
0, 0, 240, 0, 240, 0,
0, 64, 32, 16, 32, 64,
0, 32, 32, 48, 136, 112,
0, 112, 128, 176, 136, 112,
0, 136, 248, 136, 80, 32,
0, 240, 136, 240, 136, 240,
0, 120, 128, 128, 128, 120,
0, 240, 136, 136, 136, 240,
0, 248, 128, 240, 128, 248,
0, 128, 128, 240, 128, 248,
0, 120, 136, 184, 128, 120,
0, 136, 136, 248, 136, 136,
0, 112, 32, 32, 32, 112,
0, 112, 136, 8, 8, 8,
0, 136, 144, 224, 144, 136,
0, 248, 128, 128, 128, 128,
0, 136, 136, 168, 216, 136,
0, 136, 152, 168, 200, 136,
0, 112, 136, 136, 136, 112,
0, 128, 128, 240, 136, 240,
0, 104, 152, 168, 136, 112,
0, 152, 144, 240, 136, 240,
0, 240, 8, 112, 128, 120,
0, 32, 32, 32, 32, 248,
0, 112, 136, 136, 136, 136,
0, 32, 112, 136, 136, 136,
0, 136, 216, 168, 136, 136,
0, 136, 80, 32, 80, 136,
0, 32, 32, 32, 80, 136,
0, 248, 64, 32, 16, 248,
0, 120, 96, 96, 96, 120,
0, 8, 16, 32, 64, 128,
0, 120, 24, 24, 24, 120,
0, 0, 0, 136, 80, 32,
0, 0, 248, 0, 0, 0,
0, 0, 0, 32, 96, 96,
0, 136, 248, 136, 80, 32,
0, 240, 136, 240, 136, 240,
0, 120, 128, 128, 128, 120,
0, 240, 136, 136, 136, 240,
0, 248, 128, 240, 128, 248,
0, 128, 128, 240, 128, 248,
0, 120, 136, 184, 128, 120,
0, 136, 136, 248, 136, 136,
0, 112, 32, 32, 32, 112,
0, 112, 136, 8, 8, 8,
0, 136, 144, 224, 144, 136,
0, 248, 128, 128, 128, 128,
0, 136, 136, 168, 216, 136,
0, 136, 152, 168, 200, 136,
0, 112, 136, 136, 136, 112,
0, 128, 128, 240, 136, 240,
0, 104, 152, 168, 136, 112,
0, 152, 144, 240, 136, 240,
0, 240, 8, 112, 128, 120,
0, 32, 32, 32, 32, 248,
0, 112, 136, 136, 136, 136,
0, 32, 112, 136, 136, 136,
0, 136, 216, 168, 136, 136,
0, 136, 80, 32, 80, 136,
0, 32, 32, 32, 80, 136,
0, 248, 64, 32, 16, 248,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 124, 124, 124, 124, 124 );
BEGIN (* Plot_Char *)
(* Use XOR rather than OR for *)
(* the cursor. *)
Do_XOR := ( ORD( Ch ) = 128 );
IF Write_Screen_Memory THEN
BEGIN
(* Turn off timesharing while drawing *)
IF ( MultiTasker = DoubleDos ) THEN
BEGIN
TurnOffTimeSharing;
Get_Screen_Address( Graphics_Screen );
END;
(* Get byte offset in row *)
XB := SUCC( X SHR 3 );
(* Get bit offset within byte *)
XS := X AND 7;
XSL := 8 - XS;
(* Get offset of character bit *)
(* pattern. *)
K1 := ( ORD( Ch ) - 32 ) * 6;
K2 := K1 + 5;
(* OR/XOR in bits of new character. *)
(* If X is even byte address, then *)
(* simply loop over rows in the *)
(* character. If X is not even *)
(* byte address, we need to store *)
(* part of pattern in two success- *)
(* ive bytes. *)
IF ( XS = 0 ) THEN
WITH Graphics_Screen^ DO
FOR I := K1 TO K2 DO
BEGIN
XO := Scan_Line_Table[ Y ] + XB;
IF Do_XOR THEN
Screen_Image[ XO ] := Screen_Image[ XO ] XOR
Char_Bits_Table[ I ]
ELSE
Screen_Image[ XO ] := Screen_Image[ XO ] OR
Char_Bits_Table[ I ];
Y := PRED( Y );
END
ELSE
WITH Graphics_Screen^ DO
FOR I := K1 TO K2 DO
BEGIN
XO := Scan_Line_Table[ Y ] + XB;
XO1 := SUCC( XO );
IF Do_XOR THEN
BEGIN
Screen_Image[ XO ] := Screen_Image[ XO ] XOR
( Char_Bits_Table[ I ] SHR XS );
Screen_Image[ XO1 ] := Screen_Image[ XO1 ] XOR
( Char_Bits_Table[ I ] SHL XSL );
END
ELSE
BEGIN
Screen_Image[ XO ] := Screen_Image[ XO ] OR
( Char_Bits_Table[ I ] SHR XS );
Screen_Image[ XO1 ] := Screen_Image[ XO1 ] OR
( Char_Bits_Table[ I ] SHL XSL );
END;
Y := PRED( Y );
END;
(* Restore timesharing mode *)
IF ( MultiTasker = DoubleDos ) THEN
TurnOnTimeSharing;
END
ELSE
BEGIN (* Plot through BIOS the hard way *)
IF Do_XOR THEN
Point_Plot_Addr := OFS( XOR_Plot_Point )
ELSE
Point_Plot_Addr := OFS( Plot_Point );
INLINE(
$8B/$86/>X { MOV AX,[BP+>X] ;Get X position}
/$48 { DEC AX ;Decrement for 0 offset later}
/$89/$C6 { MOV SI,AX ;Save X position}
{;}
/$8B/$86/>Y { MOV AX,[BP+>Y] ;Get Y position}
/$89/$C7 { MOV DI,AX ;Save Y position}
{;}
/$31/$C0 { XOR AX,AX ;Clear AX}
/$8A/$46/<CH { MOV AL,[BP+<Ch] ;Pick up character to display}
/$2D/$20/$00 { SUB AX,32 ;Convert to 0 offset}
/$89/$C3 { MOV BX,AX}
/$D1/$E0 { SHL AX,1 ;Offset * 2}
/$D1/$E0 { SHL AX,1 ;Offset * 4}
/$01/$D8 { ADD AX,BX ;Offset * 5}
/$01/$C3 { ADD BX,AX ;Offset * 6 = offset into shape table}
/$8D/$06/>CHAR_BITS_TABLE { LEA AX,[<Char_Bits_Table] ;Get address of shape table}
/$01/$C3 { ADD BX,AX ;Get starting address this character}
{;}
/$B9/$06/$00 { MOV CX,6 ;Loop over rows in character}
{;}
/$51 {Char1: PUSH CX ;Save loop counter for rows}
/$53 { PUSH BX ;Save table offset}
{;}
/$2E/$8A/$07 { CS: MOV AL,[BX] ;Get bit pattern for this row}
/$08/$C0 { OR AL,AL ;Check if any bits on in this row}
/$74/$20 { JZ Char4 ;No -- skip display this row}
{;}
/$B9/$08/$00 { MOV CX,8 ;Loop over bits this row}
{;}
/$51 {Char2: PUSH CX ;Save loop counter for bits}
{;}
/$A8/$01 { TEST AL,1 ;See if "this" bit is turned on}
/$74/$13 { JZ Char3 ;No -- skip to next bit}
{;}
/$50 { PUSH AX ;Save bit mask}
/$56 { PUSH SI ;Save X}
/$57 { PUSH DI ;Save Y}
{;}
/$89/$F0 { MOV AX,SI ;Get X}
/$01/$C8 { ADD AX,CX ;Add offset}
/$50 { PUSH AX ;X + offset}
/$57 { PUSH DI ;Y}
/$2E/$8B/$1E/>POINT_PLOT_ADDR{ CS: MOV BX,[>Point_Plot_Addr] ;Pick up subroutine address}
/$FF/$D3 { CALL BX ;Call point plot routine}
{;}
/$5F { POP DI ;Restore Y}
/$5E { POP SI ;Restore X}
/$58 { POP AX ;Restore bit mask}
{;}
/$D0/$E8 {Char3: SHR AL,1 ;Shift bit mask to next bit}
/$59 { POP CX ;Retrieve bits counter}
/$E2/$E3 { LOOP Char2 ;and try next bit}
{;}
/$5B {Char4: POP BX ;Retrieve table offset}
/$43 { INC BX ;Point to next shape table byte}
/$89/$F8 { MOV AX,DI ;Decrement Y}
/$48 { DEC AX ; ...}
/$89/$C7 { MOV DI,AX ; ...}
/$59 { POP CX ;Retrieve rows counter}
/$E2/$CD { LOOP Char1 ;and try next row}
);
END;
END (* Plot_Char *);
(*----------------------------------------------------------------------*)
(* Display_Cursor --- Display block cursor *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_Cursor( X, Y: INTEGER );
BEGIN (* Display_Cursor *)
(* Don't display cursor while plotting *)
IF ( FlagG = Text_Plot ) THEN
Plot_Char( CHR( 128 ) , X , Y );
END (* Display_Cursor *);
(*----------------------------------------------------------------------*)
(* Display_Graphics --- show character received from port *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_Graphics( VAR Ch : CHAR );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Display_Graphics *)
(* *)
(* Purpose: Displays character received from comm. port on *)
(* screen/printer/capture file. *)
(* *)
(* Calling Sequence: *)
(* *)
(* Display_Graphics( Ch : CHAR ); *)
(* *)
(* Ch --- Character received from Comm. port. *)
(* *)
(* Calls: Async_Receive *)
(* Min *)
(* Update_Review_Pointers *)
(* TimeOfDay *)
(* TimeDiff *)
(* *)
(* Remarks: *)
(* *)
(* This routine strips out certain characters which *)
(* should not be displayed, implements the XON/XOFF protocol *)
(* in a simple-minded manner, performs output wrap, and saves *)
(* output line in the review the review buffer. *)
(* *)
(*----------------------------------------------------------------------*)
(* STRUCTURED *) CONST
CR_Ch : CHAR = ^M;
LF_Ch : CHAR = ^J;
BL_Ch : CHAR = ' ';
VAR
I : INTEGER;
L : INTEGER;
Xpos : INTEGER;
Ypos : INTEGER;
C : INTEGER;
KeyC : CHAR;
(*----------------------------------------------------------------------*)
(* Do_Graphics --- Interpret current char as graphics command *)
(*----------------------------------------------------------------------*)
PROCEDURE Do_Graphics;
BEGIN (* Do_Graphics *)
(* Get previous character and *)
(* save current character *)
Old := ORD( Prev_Ch );
Prev_Ch := Ch;
(* Set first X corrdinate *)
IF ( C > 31 ) AND ( C < 64 ) AND ( Old > 95 ) AND ( Old < 128 ) THEN
BEGIN
Hx := C;
EXIT;
END;
(* Set first Y coordinate *)
IF ( C > 31 ) AND ( C < 64 ) THEN
BEGIN
Hy := C;
EXIT;
END;
(* Set second Y coordinate *)
IF ( C > 95 ) AND ( C < 128 ) THEN
BEGIN
Ly := C;
EXIT;
END;
(* Set second X coordinate, and *)
(* plot point if necessary. *)
IF ( C > 63 ) AND ( C < 96 ) THEN
BEGIN
Lx := C;
(* Get PC screen position of point *)
XPos := TRUNC( XFactor * ( ( Hx - 32 ) * 32 + Lx - 64 ));
YPos := YMax - TRUNC( YFactor * ( ( Hy - 32 ) * 32 + Ly - 96 ));
(* Turn off timesharing while drawing *)
IF ( MultiTasker = DoubleDos ) THEN
BEGIN
TurnOffTimeSharing;
Get_Screen_Address( Graphics_Screen );
END;
(* First coordinate -- just move *)
(* to it *)
CASE FlagG OF
Vector_Plot : Draw_Line( Graphics_XPos, Graphics_YPos,
XPos, YPos );
Vector_Plot_Start: FlagG := Vector_Plot;
Point_Plot : Plot_Point( XPos, YPos );
Point_Plot_Start : FlagG := Point_Plot;
ELSE;
END (* CASE *);
(* Restore timesharing mode *)
IF ( MultiTasker = DoubleDos ) THEN
TurnOnTimeSharing;
(* Update graphics position *)
Graphics_XPos := XPos;
Graphics_YPos := YPos;
END;
END (* Do_Graphics *);